<!DOCTYPE html>
<html>
<head>
	<title></title>
	<link rel="stylesheet" type="text/css" href="../公用CSS文件/all.css" />
	<meta charset="utf-8">
	<script type="text/javascript" src="../js/jquery.min.js"></script> 	<script type="text/javascript" src="../js/js.js"></script>
</head>
<body>
<div class="dt">正则表达式概念</div>
<ul>
	<li>正则表达式是对字符串操作的一种逻辑公式，用事先定义好的一些特定字符、以及这些特定字符的组合，组成一个规则字符串，这个规则字符串用来表达对字符串的一种过滤逻辑，这些特定字符的组合被称为正则表达式</li>
	<li>正则表达式用来检索、替换那些符合某个模式的文本</li>
</ul>

<div class="dt">PHP正则表达式语法</div>
<ul>
	<li>PHP正则表达式是由'/元字符+文本字符/修饰符'这样的字符串标示，“/”为它的定界符</li>
	<li>字母、数字和反斜线\之外的字符都可以为正则表达式的定界符</li>
	<li>php正则匹配是以字节为基准，javascript则是以编码好的字符为基准(相当于php的u模式)，在计算字符长度时也一样</li>
</ul>

<div class="dt">PHP正则表达式组成</div>
<ul>
	<div class="ltable showimg">定界符</div>
	<div class="img">
		<li>字母、数字和反斜线\之外的字符都可以为正则表达式的定界符</li>
	</div>

	<div class="ltable showimg">文本字符</div>
	<div class="img">
		<li>正则表达式中文本字符可以定义为定界符内不做元字符用的字符</li>
		<li>正则匹配"\"需要至少三个"\"，而且'\\\\'等价于'\\\'，解析过程大致为两两成对转义成转义符两个字符串识别为正则转义符，之后进行正则解析，再次转义为正则普通文本字符"\"</li>
		<li>\d这类表达式无论单双引号都能直接解析为正则表达式是因为\d没有特殊的意义，但是"\数字"有特殊意义是一个特殊字符串，所以通过序列引用分组时，双引号需要写成"\\1"</li>
	</div>

	<div class="ltable showimg">元字符</div>
	<div class="img">
		<table>
			<tr>
				<th>字符</th><th>意义</th>
			</tr>
			<tr>
				<td>*</td>
				<td>匹配一个字符0次或N次</td>
			</tr>
			<tr>
				<td>+</td>
				<td>匹配一个字符至少1次</td>
			</tr>
			<tr>
				<td>{n,m}</td>
				<td>匹配一个字符n~m次，可仅指定一个，{n,}为n到无穷大(反过来则是正数无穷小)，{n}为n次</td>
			</tr>
			<tr>
				<td>?</td>
				<td>匹配0次或一个字符，追加在匹配多次的pattern后表示非贪婪匹配，追加在分组符"("后并后跟"P"可对表达式分组命名和按名称调用(?P和(?P=，它也是预搜索正则的元字符组合中的一个</td>
			</tr>
			<tr>
				<td>.</td>
				<td>通配任意一个字符，包含空格，s模式下包含空白字符</td>
			</tr>
			<tr>
				<td>^</td>
				<td>出现在整个表达式或分组表达式、预搜索表达式内部的最前一个位置表示匹配出现在行首的字符，在范围匹配符[]第一个位置出现则表示范围取反</td>
			</tr>
			<tr>
				<td>$</td>
				<td>出现在整个表达式或分组表达式、预搜索表达式内部的最前一个位置表示匹配出现在行尾的字符</td>
			</tr>
			<tr>
				<td>()</td>
				<td>分组符、预搜索，内部字符会识别为一个整体，在后面的表达式中可以用"\数字"调用该组表达式，如果内部是一个符合预搜索规则的pattern，将匹配而不返回内部匹配的结果并且分组调用将会失效</td>
			</tr>
			<tr>
				<td>[]</td>
				<td>范围匹配符，内部的每一个字符都是一个单独的可匹配值，内部组合"-"为模糊范围匹配其逻辑类似between and，u模式下可以进行unicode编码范围匹配</td>
			</tr>
		</table>
		<li>范围匹配除了unicode编码匹配外，常用的有[a-z]小写字母、[A-Z]大写字母、[0-9]所有数字</li>
		<li>表达式分组后再次被调用和在该位置完全复制一遍表达式是不一样的，其实它的意义是让分组表达式匹配的字符再次在其他位置出现，这个位置匹配的是原表达式在匹配对象中匹配到的结果而不是再次匹配</li>
		<li>表达式分组命名和调用的基本语法为(?P&lt;name&gt;)和(?P=name)，也可以使用\k或\g，分组后匹配的结果会额外返回组名为key、组索引为key的匹配结果</li>
		<li>贪婪模式是指在可进行不定次数匹配时，结果中会尽可能多的去匹配，而非贪婪模式则会尽可能少的去匹配。贪婪模式a+匹配aa只有1个结果aa，非贪婪模式则会匹配2个为a的结果</li>
		<li>php默认进行贪婪匹配，但可以通过U使整个正则进行非贪婪(小写的u为unicode模式)，同时存在?指定的非贪婪模式和U修饰符时会产生中和的负负得正的效果，?标示的pattern会进行贪婪匹配</li>
	</div>

	<div class="ltable showimg">匹配模式修饰符</div>
	<div class="img">
		<table>
			<tr>
				<th>修饰符</th><th>意义</th><th>示例</th>
			</tr>
			<tr>
				<td>i</td>
				<td>匹配不区分大小写</td>
				<td>'/a/i'，该模式</td>
			</tr>
			<tr>
				<td>s</td>
				<td>“.”号正则通配将匹配到空字符(不是空格，因为默认能匹配空格)</td>
				<td>'/./s'，该正则能匹配到换行符</td>
			</tr>
			<tr>
				<td>m</td><td>匹配内容的首和尾时采用多行识别</td><td>'/^a/'，能匹配到第二行的a</td>
			</tr>
			<tr>
				<td>x</td>
				<td>忽略正则表达式中的空白字符和不做元字符用也未转义的特殊字符</td>
				<td>'/a a/'，该正则将匹配“aa”而不是“a a”</td>
			</tr>
			<tr>
				<td>A</td>
				<td>规范整个正则只能匹配行首字符</td>
				<td>'/a/A'，该正则等价于'/^a/'</td>
			</tr>
			<tr>
				<td>U</td>
				<td>启用最小的匹配方式，术语叫非贪婪模式</td>
				<td>'/a+/u'，该正则'aa'将匹配2次'a'而不是一次'aa'</td>
			</tr>
			<tr>
				<td>e</td>
				<td>将所有字符串看成一行</td>
				<td>默认开启的模式，'/^a/'在多行中也只匹配字符串第一个字符a</td>
			</tr>
			<tr>
				<td>D</td>
				<td>对行尾采用严格的判断，如果行尾是一个换行符，默认之前的一个字符也算行尾，D模式不算</td>
				<td>'/a$/D'将不能匹配到'a\n'</td>
			</tr>
		</table>
	</div>
</ul>

<div class="dt">PHP正则表达式</div>
<ul>
	<div class="ltable showimg">正则表达式属性</div>
	<div class="img">
		<table>
			<tr>
				<th>属性</th><th>意义</th>
			</tr>
			<tr>
				<td>\w</td>
				<td>匹配字母、数字和下划线(这是通常的命名规格)，u模式能匹配语言文字(例如中文). \W为反选择</td>
			</tr>
			<tr>
				<td>\d</td>
				<td>匹配数字，\D为反选择</td>
			</tr>
			<tr>
				<td>\s</td>
				<td>匹配空白字符(空格、制表符、换行符等)，等价于[\r\n\f\t\v]。\S反选择</td>
			</tr>
			<tr>
				<td>\b</td>
				<td>匹配字符边界。字符边界是指连续的\w字符的起始和结束的位置，字符串的起始和结束也可以是字符边界。\B反选择</td>
			</tr>
			<tr>
				<td>\p</td>
				<td>匹配unicode七种基本属性的一种，\p{P}匹配unicode标点符号</td>
			</tr>
			<tr>
				<td>\k或者\g，需要组合{组名}使用</td>
				<td>标记之后的表达式为分组表达式调用</td>
			</tr>
		</table>
		<li>\b匹配字符边界，匹配到的值是长度为0的空字符串，值的出现索引位置是连续\w字符的第一个值和最后一个值的索引位置</li>
		<li>\k和\g的语法是在5.2~5.6版本的更新中加进去的</li>
	</div>

	<div class="ltable showimg">元字符组合</div>
	<div class="img">
		<table>
			<tr>
				<th>字符</th><th>说明</th>
			</tr>
			<tr>
				<td>pattern+?</td>
				<td>使用非贪婪模式匹配至少一个pattern</td>
				<td>U模式全局非贪婪模式会负负得正进行贪婪匹配</td>
			</tr>
			<tr>
				<td>pattern*?</td>
				<td>使用非贪婪模式匹配0到无穷个字符</td>
				<td>U模式全局非贪婪模式会负负得正进行贪婪匹配</td>
			</tr>
			<tr>
				<td>pattern{m,n}</td>
				<td>使用非贪婪模式匹配m到n个字符，计数匹配只要匹配个数未限定就会产生贪婪或非贪婪的区别</td>
				<td>U模式全局非贪婪模式会负负得正进行贪婪匹配</td>
			</tr>
			<tr>
				<td>[^pattern]</td>
				<td>pattern范围取反</td>
				<td>范围匹配取反、模糊序列范围、纯pattern是可以并存的</td>
			</tr>
			<tr>
				<td>[pattern-pattern]</td>
				<td>模糊范围匹配，常用[a-z]、[A-Z]、[0-9]，u模式下可以进行unicode编码范围匹配(比如匹配中文[\x{4e00}-\x{9fa5}]，这是因为unicode编码有一个序列)</td>
				<td>范围匹配取反、模糊序列范围、纯pattern是可以并存的</td>
			</tr>
		</table>
		<li>范围取反必须要有一个不在范围内的字符，否定预搜索则不需要</li>
	</div>

	<div class="ltable showimg">正则预搜索</div>
	<div class="img">
		<table>
			<tr>
				<th>表达式</th>
				<th>说明</th>
				<td>使用示范</td>
				<td>备注</td>
			</tr>
			<tr>
				<td>(?:pattern)</td>
				<td>非获取匹配，匹配pattern但不获取匹配结果</td>
				<td>/我(?:是)/，可匹配"我是"和"我"但结果只含有"我"</td>
				<td>js和php实际上都等价于pattern，可能是语法不支持</td>
			</tr>
			<tr>
				<td>(?=pattern)</td>
				<td>非获取匹配，正向肯定预查</td>
				<td>/我(?=是)/，可匹配"我是"但结果只含有我</td>
				<td>在任何匹配pattern的字符串开始处向左匹配查找字符串(所以该表达式必须在最右侧)</td>
			</tr>
			<tr>
				<td>(?!pattern)</td>
				<td>非获取匹配，正向否定预搜索</td>
				<td>/我(?!是)/，可匹配"我"和"我"+任意"是"之外的字符但结果只含有我</td>
				<td>在任何不匹配pattern的字符串开始处向左匹配查找字符串(所以该表达式必须在最右侧)</td>
			</tr>
			<tr>
				<td>(?<=pattern)</td>
				<td>非获取匹配，反向肯定预搜索</td>
				<td>/(?<=是)我/，可匹配"是我"但结果只含有我</td>
				<td>在任何匹配pattern的字符串开始处向右匹配查找字符串(所以该表达式必须在最左侧)</td>
			</tr>
			<tr>
				<td>(?<!pattern)</td>
				<td>非获取匹配，反向否定预搜索</td>
				<td>/(?<!是)我/，可匹配"我"和任意"是"之外的字符+"我"但结果只含有我</td>
				<td>在任何匹配pattern的字符串开始处向右匹配查找字符串(所以该表达式必须在最左侧)</td>
			</tr>
		</table>
		<li>预搜索的取反规则和[^pattern]不一致，预搜索取反所在位置可以没有字符，但[^pattern]必须有一个不是pattern的字符，所以预搜索有个名称叫做零宽断言，反向预搜索也叫负向零宽</li>
		<li>预搜索作为一个整体pattern，不与左右的任何元字符产生作用^(?=1)1等价于(?=1)^1，因为在执行时，预搜索部分会单独先执行</li>
		<li>以上测试细节对应的PHP版本为7.4.3</li>
	</div>
</ul>

<div class="dt">特殊字符和Unicode属性</div>
<ul>
	<div class="ltable showimg">特殊空字符</div>
	<div class="img">
		<table>
			<tr>
				<th>符号</th><th>说明</th><th>意义</th>
			</tr>
			<tr>
				<td>换行符</td>
				<td>\n</td>
				<td>本来意义为光标下移一行(newLine)，unix系统同时回到行首</td>
			</tr>
			<tr>
				<td>回车符</td>
				<td>\r</td>
				<td>光标回到行首(return)</td>
			</tr>
			<tr>
				<td>换页符</td>
				<td>\f</td>
				<td>form feed,换页</td>
			</tr>
			<tr>
				<td>制表符</td>
				<td>\t</td>
				<td>table,表格</td>
			</tr>
			<tr>
				<td>垂直制表符</td>
				<td>v</td>
				<td>vertical table，垂直制表</td>
			</tr>
		</table>
	</div>

	<div class="ltable showimg">unicode七种基本属性</div>
	<div class="img">
		<table>
			<tr>
				<th>属性标记</th><th>意义</th>
			</tr>
			<tr>
				<td>L</td>
				<td>字母，每一个汉字也算一个字母</td>
			</tr>
			<tr>
				<td>P</td>
				<td>标点符号，大致可以区分为半角全角两种，全角字符占一个中文宽度半角符号占半个中文宽度</td>
			</tr>
			<tr>
				<td>Z</td>
				<td>分隔符，空格和换行符</td>
			</tr>
			<tr>
				<td>M</td>
				<td>标记，"a⃞"a后面那个框(其实这是html显示问题，编辑器字母在框的内部)，大致可以认为是标点符号和文字外对文本进行重点、意义的着重标记用的符号</td>
			</tr>
			<tr>
				<td>S</td>
				<td>符号，一切度量衡体系的符号，如$、¥</td>
			</tr>
			<tr>
				<td>N</td>
				<td>数字，包含罗马数字、阿拉伯数字，中文数字不在其中</td>
			</tr>
			<tr>
				<td>C</td>
				<td>其他字符</td>
			</tr>
		</table>
		<li>unicode属性除了七种基本属性，还有其下的子属性，详细说明可以访问www.unicode.org/</li>
	</div>
</ul>


<div class="dt">PHP正则表达式相关函数</div>
<ul>
	<div class="ltable showimg">preg库函数</div>
	<div class="img">
		<table>
			<tr>
				<th>函数</th><th>作用</th><th>参数</th><th>返回值</th>
			</tr>
			<tr>
				<td>preg_match</td><td>执行正则表达式--匹配到一次后停止</td><td>str正则 &nbsp;&nbsp;str&nbsp; &nbsp;【变量&nbsp; &nbsp;flag方式int=0&nbsp; &nbsp;offset=0】</td><td>匹配到的次数，第三参数填充匹配结果，flag=256时该数组记录下标</td>
			</tr>
			<tr>
				<td>preg_match_all</td><td>执行正则表达式--尽可能的匹配</td><td>str正则 &nbsp;&nbsp;str&nbsp; &nbsp;【变量&nbsp; &nbsp;flag方式int=0&nbsp; &nbsp;offset=0】</td><td>匹配到的次数，第三参数填充匹配结果，flag=256时该数组记录下标</td>
			</tr>
			<tr>
				<td>preg_replace</td><td>正则替换（但search也可以为字符）</td><td>正则 &nbsp;&nbsp;replacement &nbsp;&nbsp;执行对象 &nbsp;&nbsp;【最大次数int=-1 &nbsp;变量】</td><td>替换后的结果，第五参数填充替换次数</td>
			</tr>
			<tr>
				<td> preg_quote</td><td>转义正则特殊字符</td><td>字符串</td><td>转义后的字符串(可安全在正则表达式定界符中使用)</td>
			</tr>
			<tr>
				<td>preg_filter</td><td>正则替换(次数为0过滤不返回subject)</td><td>正则 &nbsp;&nbsp;replacement &nbsp;&nbsp;执行对象 &nbsp;&nbsp;【最大次数int=-1 &nbsp;变量】</td><td>替换后的结果（次数为0过滤掉），第五参数填充替换次数</td>
			</tr>
			<tr>
				<td>preg_replace_callback</td><td>以回调函数替换正则检索字符</td><td>正则 &nbsp;&nbsp;回调函数 &nbsp;&nbsp;执行对象 &nbsp;&nbsp;最大次数int=-1 &nbsp;&nbsp;变量</td><td>数组或字符串</td>
			</tr>
			<tr>
				<td>preg_split</td><td>以正则式分割字符串为数组</td><td>str正则 &nbsp;&nbsp;str &nbsp;&nbsp;分割段数int=-1 &nbsp;&nbsp;flag方式int=0</td><td>数组,当flag=1时过滤空字符,=2时单独保留正则()中指定字符,=4记录漂移量</td>
			</tr>
			<tr>
				<td>preg_grep</td><td>返回数组中key可以和正则匹配的元素数组</td><td>str正则 &nbsp;&nbsp;数组 &nbsp;&nbsp;flag方式int=0</td><td>数组，如果flag为任意非0数字返回不匹配的元素数组</td>
			</tr>

		</table>
		<li>preg库涉及字符串替换，其参数可以为字符串，就可以为字符串的索引数组，相对的也可能返回数组</li>
		<li>preg_replace_callback函数的回调函数会在检索到匹配字符后传入该函数调用，它内部需要返回一个字符串</li>
		<li>preg库函数接受结果的变量，如果仅进行一次匹配，返回一维数组，多次返回二维，单次匹配的结果会包含正则表达式整体之后列出单组的结果(表达式分组)</li>
	</div>
</ul>

<div class="dt">附注信息</div>
<ul>
	<li>界定符中如果没有包含空格任何字符，'//'，将会匹配到strlen（字符串）+1个元素</li>
	<li>PHP有两套正则函数库，一个是PCRE库（preg前缀函数），一个是POSUIX库（ereg前缀），前者效率略高</li>
</ul>
</body>
</html>